/**
 * 
 */
package edu.umd.clip.lm.model.decoding;

import java.util.*;
import java.util.concurrent.atomic.AtomicLong;

import edu.umd.clip.lm.model.*;

/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 */
public class TrellisNodeItem implements Cloneable {
	protected ProbTree tree;
	private double prevProb;

	private final static AtomicLong lastid = new AtomicLong();
	private final long id = lastid.incrementAndGet();
	
	private IdentityHashMap<TrellisNodeItem,TrellisNodeItem> prevItems;
	private IdentityHashMap<TrellisNodeItem,TrellisNodeItem> nextItems;
	
	public final int time;
	/**
	 * @param tree
	 * @param prevProb
	 */
	public TrellisNodeItem(ProbTree tree, double prevProb, int time) {
		this.tree = tree;
		this.prevProb = prevProb;
		this.time = time;
	}

	public double getPrevProb() {
		return prevProb;
	}
	
	public void setPrevProb(double p) {
		prevProb = p;
	}
	
	public void addPrevProb(double prob) {
		prevProb += prob;
	}
	
	@Override
	public TrellisNodeItem clone() {
		TrellisNodeItem copy = new TrellisNodeItem((ProbTree)tree.clone(), 0, time);
		return copy;
	}
	
	public double getProb() {
		return prevProb * tree.getTotalProb();
	}
	
	public String toString() {
		return Long.toString(id) + "@" + Integer.toString(time);
	}

	public final IdentityHashMap<TrellisNodeItem, TrellisNodeItem> getPrevItemsMap() {
		return prevItems;
	}

	public final Set<TrellisNodeItem> getPrevItems() {
		return prevItems == null ? null : prevItems.keySet();
	}

	public final Set<TrellisNodeItem> getNextItems() {
		return nextItems == null ? null : nextItems.keySet();
	}

	public void clearNextItems() {
		if (nextItems != null) nextItems.clear();
	}
	
	public void clearPrevItems() {
		if (prevItems != null) prevItems.clear();
	}
	
	public void addPrevItem(TrellisNodeItem item) {
		if (prevItems == null) prevItems = new IdentityHashMap<TrellisNodeItem, TrellisNodeItem>();
		prevItems.put(item, item);
	}
	
	public TrellisNodeItem removePrevItem(TrellisNodeItem item) {
		if (prevItems != null) return prevItems.remove(item);
		return null;
	}
	
	public void addNextItem(TrellisNodeItem item) {
		if (nextItems == null) nextItems = new IdentityHashMap<TrellisNodeItem, TrellisNodeItem>();
		nextItems.put(item, item);
	}
	
	public TrellisNodeItem removeNextItem(TrellisNodeItem item) {
		if (nextItems != null) return nextItems.remove(item);
		return null;
	}
	
	public final void setPrevItems(IdentityHashMap<TrellisNodeItem, TrellisNodeItem> prevItems) {
		this.prevItems = prevItems;
	}

	public final IdentityHashMap<TrellisNodeItem, TrellisNodeItem> getNextItemsMap() {
		return nextItems;
	}

	public final void setNextItems(IdentityHashMap<TrellisNodeItem, TrellisNodeItem> nextItems) {
		this.nextItems = nextItems;
	}
	
	
}
